#!/usr/bin/perl -wc

package RFCMail::ESMTP::Grammar::Base;

use strict;
use Exporter qw(import);
use RFCMail::Common::Grammar qw(TEXT_RE
				ATEXT_RE
				QCONTENT_RE);

my @BASE =
    qw(
       SNUM_RE
       IPV4_ADDR_LIT_RE
       ADDR_LIT_RE
       ATOM_RE
       DOT_STRING_RE
       QUOTED_STRING_RE
       STRING_RE
       LOCAL_PART_RE
       LDH_STR_RE
       SUB_DOMAIN_RE
       DOMAIN_RE
       AT_DOMAIN_RE
       A_D_L_RE
       MAILBOX_RE
       PATH_RE
       REVERSE_PATH_RE
       FORWARD_PATH_RE
       ESMTP_VALUE_RE
       ESMTP_KEYWORD_RE
       ESMTP_PARAM_RE
       PARAMETERS_RE
      );

my @CLIENT =
    qw(
       REPLY_CODE_RE
       EHLO_LINE_RE
       EHLO_GREET_RE
       GREETING_RE
       REPLY_LINE_RE
      );

my @SERVER =
    qw(
       COMMAND_RE
       MAIL_ARGS_RE
       RCPT_ARGS_RE
       DOMAIN_ARG_RE
       STRING_ARG_RE
       OPT_STRING_ARG_RE
      );

our @EXPORT = (@BASE);

our @EXPORT_OK = (@CLIENT, @SERVER);

our %EXPORT_TAGS =
    (
     base => \@BASE,
     client => \@CLIENT,
     server => \@SERVER,
    );


# Basic common regular expressions from RFC 2821, sections 4.1.2 and
# 4.1.3. See the pod file for additional notes.

use constant SNUM_RE
    => qr'\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]'o;

use constant IPV4_ADDR_LIT_RE
    => qr"@{[SNUM_RE]}(?:\.@{[SNUM_RE]}){3}"o;

use constant ADDR_LIT_RE # not fully implemented
    => qr"\[@{[IPV4_ADDR_LIT_RE]}\]"o;

use constant ATOM_RE
    => qr"@{[ATEXT_RE]}+"o;

use constant DOT_STRING_RE
    => qr"@{[ATOM_RE]}(?:\.@{[ATOM_RE]})*"o;

use constant QUOTED_STRING_RE
    => qr"\"@{[QCONTENT_RE]}*\""o;

use constant STRING_RE
    => qr"@{[ATOM_RE]}|@{[QUOTED_STRING_RE]}"o;

use constant LOCAL_PART_RE
    => qr"@{[DOT_STRING_RE]}|@{[QUOTED_STRING_RE]}"o;

use constant LDH_STR_RE
    => qr'[[:alnum:]-]*[[:alnum:]]'o;

use constant SUB_DOMAIN_RE
    => qr"[[:alnum:]]@{[LDH_STR_RE]}?"o;

use constant DOMAIN_RE
    => qr"(?:@{[SUB_DOMAIN_RE]}(?:\.@{[SUB_DOMAIN_RE]})+)|@{[ADDR_LIT_RE]}"o;

use constant AT_DOMAIN_RE
    => qr"\@@{[DOMAIN_RE]}"o;

use constant A_D_L_RE
    => qr"@{[AT_DOMAIN_RE]}(?:,@{[AT_DOMAIN_RE]})*"o;

use constant MAILBOX_RE
    => qr"@{[LOCAL_PART_RE]}\@@{[DOMAIN_RE]}"o;

use constant PATH_RE
    => qr"<(?:@{[A_D_L_RE]}:)?@{[MAILBOX_RE]}>"o;

use constant REVERSE_PATH_RE # modified
    => qr"<>|@{[PATH_RE]}"o;

use constant FORWARD_PATH_RE # modified
    => qr"(?i:<postmaster>)|@{[PATH_RE]}"o;

use constant ESMTP_VALUE_RE
    => qr'[\041-\074\076-\177]+'o;

use constant ESMTP_KEYWORD_RE
    => qr'[[:alnum:]][[:alnum:]-]*'o;

use constant ESMTP_PARAM_RE
    => qr"@{[ESMTP_KEYWORD_RE]}(?:=@{[ESMTP_VALUE_RE]})?"o;

use constant PARAMETERS_RE # an addition
    => qr"@{[ESMTP_PARAM_RE]}(?: @{[ESMTP_PARAM_RE]})*"o;


# For ESMTP clients.

use constant REPLY_CODE_RE # based on informal definition in section 4.2.1
    => qr'[1-5][0-5]\d'o;

use constant EHLO_LINE_RE # section 4.1.1.1
    => qr"@{[ESMTP_KEYWORD_RE]}(?: [\041-\177]+)*"o;

use constant EHLO_GREET_RE # section 4.1.1.1 (includes NUL: nasty!)
    => qr'[\x00-\x09\x0B\x0C\x0E-\x7F]+'o;

use constant GREETING_RE # section 4.2, "corrected"
    => qr"\A220 (@{[DOMAIN_RE]})(?: (@{[TEXT_RE]}))\Z"o;

use constant REPLY_LINE_RE # section 4.2, modified
    => qr"\A(@{[REPLY_CODE_RE]})(?:([- ])(@{[TEXT_RE]}*))\Z"o;


# For ESMTP servers.

use constant COMMAND_RE
    => qr"\A([[:alpha:]]+)(?: *\Z| (@{[TEXT_RE]}+?) *\Z)"o;

use constant MAIL_ARGS_RE
    => qr"\A(?i:FROM:)(@{[REVERSE_PATH_RE]})(?: (@{[PARAMETERS_RE]}))?\z"o;

use constant RCPT_ARGS_RE
    => qr"\A(?i:TO:)(@{[FORWARD_PATH_RE]})(?: (@{[PARAMETERS_RE]}))?\z"o;

use constant DOMAIN_ARG_RE # for EHLO and HELO
    => qr"\A(@{[DOMAIN_RE]})\z"o;

use constant STRING_ARG_RE # for VRFY and EXPN
    => qr"\A(@{[STRING_RE]})\z"o;

use constant OPT_STRING_ARG_RE # for NOOP and HELP
    => qr"\A(@{[STRING_RE]})?\z"o;


1;
